package com.ssy.lingxi.platform.template.service.serviceimpl.web;

import cn.hutool.core.collection.CollectionUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.CollectionPageUtil;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberInnerControllerFeign;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberLevelRightCreditControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignIdVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignLrcVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignRegisterQueryVO;
import com.ssy.lingxi.platform.manage.api.feign.inner.AreaControllerFeign;
import com.ssy.lingxi.platform.template.service.entity.collect.MemberProcessCollect;
import com.ssy.lingxi.platform.template.service.entity.door.MemberProcess;
import com.ssy.lingxi.platform.template.service.entity.door.QMemberProcess;
import com.ssy.lingxi.platform.template.service.model.bo.AreaBO;
import com.ssy.lingxi.platform.template.service.model.bo.CategoryBO;
import com.ssy.lingxi.platform.template.service.model.dto.common.CollectDTO;
import com.ssy.lingxi.platform.template.service.model.dto.common.IdDTO;
import com.ssy.lingxi.platform.template.service.model.dto.common.IdListDTO;
import com.ssy.lingxi.platform.template.service.model.dto.web.SaveProcessDTO;
import com.ssy.lingxi.platform.template.service.model.qo.MemberProcessQO;
import com.ssy.lingxi.platform.template.service.model.vo.web.MemberProcessListVO;
import com.ssy.lingxi.platform.template.service.model.vo.web.MemberProcessMainVO;
import com.ssy.lingxi.platform.template.service.repository.MemberProcessCollectRepository;
import com.ssy.lingxi.platform.template.service.repository.MemberProcessRepository;
import com.ssy.lingxi.platform.template.service.service.web.MemberProcessWebService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * @menu web - 会员加工门户 - 业务实现层
 * @author fhj
 * @version 2.0.0
 * @date 2021/04/14
 */
@Slf4j
@Service
public class MemberProcessWebServiceImpl implements MemberProcessWebService {

    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private MemberProcessRepository memberProcessRepository;
    @Resource
    private MemberLevelRightCreditControllerFeign memberLevelRightCreditControllerFeign;
    @Resource
    private MemberInnerControllerFeign memberInnerControllerFeign;
    @Resource
    private AreaControllerFeign areaControllerFeign;
    @Resource
    private MemberProcessCollectRepository memberProcessCollectRepository;

    @Override
    @Transactional
    @ApiOperation(value = "保存当前登录会员的加工门户")
    public Wrapper<Void> saveCurrMemberProcess(SaveProcessDTO dto, UserLoginCacheDTO user) {
        //校验（只有是服务提供者且企业类型是企业会员或个人会员才能创建加工门户
        if(!user.getMemberRoleType().equals(RoleTypeEnum.SERVICE_PROVIDER.getCode())) {
            return Wrapper.fail("角色类型不是服务提供者, 不能创建加工门户");
        }
        if(!(user.getMemberType().equals(MemberTypeEnum.MERCHANT.getCode()) || user.getMemberType().equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode()))) {
            return Wrapper.fail("会员类型不是企业会员或个人会员, 不能创建加工门户");
        }

        //默认省、市编码都为0（所有/所有）
        List<String> provinceCodes = Stream.of("0").collect(toList());
        List<String> cityCodes = Stream.of("0").collect(toList());
        if(dto.getAreaBOList().stream().noneMatch(a -> a.getProvinceCode().equals("0"))) {
            provinceCodes = dto.getAreaBOList().stream().map(AreaBO::getProvinceCode).collect(Collectors.toList());
            cityCodes = dto.getAreaBOList().stream().filter(a -> !a.getCityCode().equals("0")).map(AreaBO::getCityCode).collect(Collectors.toList());

            List<String> feignCodes = dto.getAreaBOList().stream().filter(a -> a.getCityCode().equals("0")).map(AreaBO::getProvinceCode).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(feignCodes)) {
                Wrapper<List<String>> cityCodesWrapper = areaControllerFeign.findCityCodeByProvinceCode(feignCodes);
                if(cityCodesWrapper.getCode() == ResponseCode.SUCCESS.getCode() && CollectionUtil.isNotEmpty(cityCodesWrapper.getData())) {
                    cityCodes.addAll(cityCodesWrapper.getData());
                }
            }
        }

        //调用会员服务 -> 根据会员ID和角色ID获取平台会员的等级、注册年数、信用积分
        MemberFeignVO memberFeignVO = new MemberFeignVO();
        memberFeignVO.setMemberId(user.getMemberId());
        memberFeignVO.setRoleId(user.getMemberRoleId());
        Wrapper<MemberFeignLrcVO> platformMemberLrcWrapper = memberLevelRightCreditControllerFeign.getPlatformMemberLrc(memberFeignVO);
        if(platformMemberLrcWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("调用会员服务失败：{}", platformMemberLrcWrapper.getMessage());
            return Wrapper.fail(ResponseCode.SERVICE_MERCHANT_MEMBER_ERROR);
        }
        //调用会员服务 -> 根据会员Id查询会员注册信息
        MemberFeignIdVO memberFeignIdVO = new MemberFeignIdVO();
        memberFeignIdVO.setMemberId(user.getMemberId());
        Wrapper<MemberFeignRegisterQueryVO> memberRegisterInfoWrapper = memberInnerControllerFeign.getMemberRegisterInfo(memberFeignIdVO);
        if(memberRegisterInfoWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("调用会员服务失败：{}", memberRegisterInfoWrapper.getMessage());
        }

        //保存会员加工门户信息
        MemberProcess memberProcess = memberProcessRepository.findByMemberIdAndRoleId(user.getMemberId(), user.getMemberRoleId());
        memberProcess = memberProcess != null ? memberProcess : new MemberProcess();
        memberProcess.setMemberId(user.getMemberId());
        memberProcess.setRoleId(user.getMemberRoleId());
        memberProcess.setCategoryBOList(dto.getCategoryBOList());
        memberProcess.setYearProcessAmount(dto.getYearProcessAmount());
        memberProcess.setPlantArea(dto.getPlantArea());
        memberProcess.setStaffNum(dto.getStaffNum());
        memberProcess.setAreaBOList(dto.getAreaBOList());
        memberProcess.setLogo(dto.getLogo());
        memberProcess.setDescribe(dto.getDescribe());
        memberProcess.setSlideshowBOList(dto.getSlideshowBOList());
        memberProcess.setCompanyPics(dto.getCompanyPics());
        memberProcess.setHonorPics(dto.getHonorPics());
        memberProcess.setAlbumName(dto.getAlbumName());
        memberProcess.setAlbumUrl(dto.getAlbumUrl());
        memberProcess.setAboutSeo(dto.getAboutSeo());
        memberProcess.setAreas(dto.getAreaBOList().stream().map(a -> a.getProvince() + "/" + a.getCity()).collect(Collectors.joining("，")));
        memberProcess.setProvincesCodeList(String.join("，", provinceCodes));
        memberProcess.setCityCodeList(String.join("，", cityCodes));
        memberProcess.setMemberName(user.getCompany());
        memberProcess.setLevelTag(platformMemberLrcWrapper.getData().getLevelTag());
        memberProcess.setRegisterYears(platformMemberLrcWrapper.getData().getRegisterYears());
        memberProcess.setCreditPoint(platformMemberLrcWrapper.getData().getCreditPoint());
        memberProcess.setRegisteredCapital(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getRegisteredCapital() : null);
        memberProcess.setEstablishmentDate(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getEstablishmentDate() : null);
        memberProcess.setBusinessLicence(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getBusinessLicence() : null);
        memberProcess.setRegisterArea(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getRegisterArea() : null);
        memberProcess.setRegisterAddress(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getRegisterAddress() : null);
        memberProcessRepository.saveAndFlush(memberProcess);

        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "获取当前登录会员的加工门户")
    public Wrapper<MemberProcess> findCurrMemberProcess(UserLoginCacheDTO user) {
        return Wrapper.success(memberProcessRepository.findByMemberIdAndRoleId(user.getMemberId(), user.getMemberRoleId()));
    }

    @Override
    @ApiOperation(value = "加工门户列表")
    public Wrapper<PageData<MemberProcessListVO>> memberProcessList(MemberProcessQO qo) {
        //查询表实体 - 加工门户
        QMemberProcess memberProcess = QMemberProcess.memberProcess;

        //查询条件构造 - 搜索条件
        BooleanBuilder predicates = new BooleanBuilder();

        //搜索条件 - 年加工额。
        if(qo.getYearProcessAmount() != null) {
            predicates.and(memberProcess.yearProcessAmount.eq(qo.getYearProcessAmount()));
        }
        //搜索条件 - 省编码。
        if(StringUtils.isNotBlank(qo.getProvinceCode())) {
            predicates.and(
                    memberProcess.provincesCodeList.like("%" + qo.getProvinceCode() + "%")
                            .or(memberProcess.provincesCodeList.eq("0"))
            );
        }
        //搜索条件 - 市编码。
        if(StringUtils.isNotBlank(qo.getCityCode())) {
            predicates.and(
                    memberProcess.cityCodeList.like("%" + qo.getCityCode() + "%")
                            .or(memberProcess.cityCodeList.eq("0"))
            );
        }

        //查询
        List<MemberProcess> list = jpaQueryFactory.select(memberProcess).from(memberProcess).where(predicates)
                .orderBy(memberProcess.createTime.desc()).fetch();;
        if(CollectionUtil.isEmpty(list)) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        //搜索条件 - 主要加工种类。
        if(qo.getCategoryId() != null) {
            list = list.stream().filter(a ->
                    a.getCategoryBOList().stream().anyMatch(b ->
                            (b.getFirstId() != null && b.getFirstId().equals(qo.getCategoryId())) ||
                                    (b.getSecondId() != null && b.getSecondId().equals(qo.getCategoryId())) ||
                                    (b.getThirdlyId() != null && b.getThirdlyId().equals(qo.getCategoryId()))
                    )
            ).collect(toList());
        }

        //获取总记录数
        long totalCount = list.size();

        //对集合数据进行分页
        list = CollectionPageUtil.pageList(list, qo.getCurrent(), qo.getPageSize());

        //封装
        List<MemberProcessListVO> memberProcessListVOList = list.stream().map(a -> {
            //拷贝
            MemberProcessListVO vo = new MemberProcessListVO();
            BeanUtils.copyProperties(a, vo);

            //格式化一级主营加工种类
            vo.setCategoryBOList(
                    a.getCategoryBOList().stream().map(CategoryBO::getFirstName).collect(Collectors.joining("|"))
            );

            //默认先满星
            if(a.getAvgTradeCommentStar() == null || a.getAvgTradeCommentStar() == 0) {
                a.setAvgTradeCommentStar(5);
            }

            return vo;
        }).collect(toList());

        return Wrapper.success(new PageData<>(totalCount, memberProcessListVOList));
    }

    @Override
    @ApiOperation(value = "加工门户主页")
    public Wrapper<MemberProcessMainVO> memberProcessMain(IdDTO dto, UserLoginCacheDTO user) {
        //获取加工门户
        MemberProcess memberProcess = memberProcessRepository.findById(dto.getId()).orElse(null);
        if(memberProcess == null) {
            return Wrapper.fail("根据ID找不到加工门户");
        }

        //拷贝
        MemberProcessMainVO memberProcessMainVO = new MemberProcessMainVO();
        BeanUtils.copyProperties(memberProcess, memberProcessMainVO);

        //收藏状态
        if(user != null) {
            memberProcessMainVO.setCollectStatus(memberProcessCollectRepository.existsByProcessIdAndMemberIdAndUserId(memberProcess.getId(), user.getMemberId(), user.getUserId()));
        }

        //默认先满星
        if(memberProcessMainVO.getAvgTradeCommentStar() == null || memberProcessMainVO.getAvgTradeCommentStar() == 0) {
            memberProcessMainVO.setAvgTradeCommentStar(5);
        }

        return Wrapper.success(memberProcessMainVO);
    }

    @Override
    @ApiOperation(value = "根据加工门户ID集合获取加工门户")
    public Wrapper<List<MemberProcess>> findByIdIn(IdListDTO dto) {
        return Wrapper.success(memberProcessRepository.findAllById(dto.getIdList()).stream().sorted(Comparator.comparingInt(a -> dto.getIdList().indexOf(a.getId()))).collect(toList()));
    }

    @Override
    @Transactional
    @ApiOperation(value = "收藏/取消收藏")
    public Wrapper<Void> collect(CollectDTO dto, UserLoginCacheDTO user) {
        if(dto.getStatus()) {
            if(memberProcessCollectRepository.existsByProcessIdAndMemberIdAndUserId(dto.getId(), user.getMemberId(), user.getUserId())) {
                return Wrapper.fail("不能重复收藏，请刷新页面");
            }
            MemberProcessCollect collect = new MemberProcessCollect();
            collect.setProcessId(dto.getId());
            collect.setMemberId(user.getMemberId());
            collect.setUserId(user.getUserId());
            memberProcessCollectRepository.saveAndFlush(collect);
        }else {
            memberProcessCollectRepository.deleteByProcessIdAndMemberIdAndUserId(dto.getId(), user.getMemberId(), user.getUserId());
        }

        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "收藏列表")
    public Wrapper<PageData<MemberProcess>> collectList(PageVO dto, UserLoginCacheDTO user) {
        //按收藏时间倒序获取当前用户收藏的加工门户ID
        Pageable pageable = PageRequest.of(dto.getCurrent() - 1, dto.getPageSize(), Sort.by("createTime").descending());
        Page<MemberProcessCollect> page = memberProcessCollectRepository.findAllByMemberIdAndUserId(user.getMemberId(), user.getUserId(), pageable);
        List<MemberProcessCollect> memberProcessCollectList = page.getContent();
        if(CollectionUtil.isEmpty(memberProcessCollectList)) {
            log.info("当前用户没有收藏的加工门户");
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
        List<Long> memberProcessIdList = memberProcessCollectList.stream().map(MemberProcessCollect::getProcessId).collect(toList());

        //根据收藏的加工ID获取加工门户
        List<MemberProcess> memberProcessList = memberProcessRepository.findAllById(memberProcessIdList);

        //组装收藏时间
        memberProcessList = memberProcessList.stream().peek(a -> a.setCreateTime(
                memberProcessCollectList.stream().filter(b ->
                        b.getProcessId().equals(a.getId())
                ).map(MemberProcessCollect::getCreateTime).findFirst().orElse(null)
        )).sorted(Comparator.comparingInt(a -> memberProcessIdList.indexOf(a.getId()))).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(page.getTotalElements(), memberProcessList));
    }
}
